﻿using Server.MessageModule;
using Server.MessageModule.Message;
using Server.MessageModule.MessageProcessor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Server.Network
{
    class ClientManager
    {
        public const int SERVER_PORT = 6969;
        private TcpListener tcpListener;
        private Thread listenThread;
        private IMessageReceiptable _messageDispatcher = null;
        public IMessageReceiptable MessageDispatcher { get { return _messageDispatcher; } set { _messageDispatcher = value; } }

        public ClientManager()
        {
        }

        public void start()
        {
            // Get server info
            String hostname = Dns.GetHostName();
            IPHostEntry ipAddress = Dns.GetHostEntry(hostname);
            // Log
            Console.WriteLine("Server started...");
            Console.WriteLine("Server info:\nIP");
            for (int i = 0; i < ipAddress.AddressList.Count(); i++)
            {
                Console.WriteLine(ipAddress.AddressList[i].ToString());
            }
            Console.WriteLine("Port\n" + SERVER_PORT);

            // Create listener
            tcpListener = new TcpListener(IPAddress.Any, SERVER_PORT);
            // create other thread for each client
            listenThread = new Thread(new ThreadStart(ListenForClients));
            listenThread.Start();
            Console.WriteLine("\nListening for client...");
        }

        private void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = tcpListener.AcceptTcpClient();

                //create a thread to handle communication 
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }

        private void HandleClientComm(object client)
        {

            TcpClient tcpClient = (TcpClient)client;

            // Receipt
            System.Console.WriteLine("Established connection with client: " + (tcpClient.Client.RemoteEndPoint as IPEndPoint).Address.ToString());

            NetworkStream clientStream = tcpClient.GetStream();
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += timer_Elapsed;
            timer.Interval = 1000;
            timer.Start();

            byte[] message = new byte[8192];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //blocks until a client sends a message
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch
                {
                    //a socket error has occured
                    break;
                }

                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    break;
                }

                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                string msg = encoder.GetString(message, 0, bytesRead);
                string[] list = msg.Split('\n');
                int n = list.Length;
                for (int i = 0; i < n - 1; i++ )
                {
                    _countMessage++;
                    onRecriptNetworkMessage(list[i]);
                }
                //System.Console.WriteLine(msg);
                //System.Console.WriteLine("---------");
            }
            tcpClient.Close();
        }

        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            System.Console.WriteLine("mps: " + _countMessage);
            _countMessage = 0;
        }

        private int _countMessage = 0;

        private void onRecriptNetworkMessage(String data)
        {
            if (_messageDispatcher == null)
                return;
            //System.Console.WriteLine(data);
            //System.Console.WriteLine("---------");
            INetworkMessage msg = NetworkMessageFactory.messageFromJson(data);
            if (msg == null)
                return;
            if (_messageDispatcher != null)
                _messageDispatcher.onReceiptMessage(msg);
        }
    }
}
